Could not load the default credentials.
#blogged Could not load the default credentials エラーについて - ぽ靴な缶
google-auth-library が認証情報を見つけられていない or timeout している
Google Cloud Function - Error: Could not load the default credentials. · Issue #798 · googleapis/google-auth-library-nodejs
GCP 環境上で動作させる際に、認証情報を渡さなくても実行環境上で探してくれるのだが、失敗したり timeout したりしてエラーになった場合に起きる
サーバー間での本番環境アプリケーションの認証の設定  |  認証  |  Google Cloud
Firebase ADC(Application Default Credentials)
回避策
Service Account のキーを発行して一緒にデプロイし GOOGLE_APPLICATION_CREDENTIALS に渡す
process.env.GOOGLE_APPLICATION_CREDENTIALS = './my-secret.json';
鍵の管理、サービスアカウントの role の管理、デプロイフローに影響するのであまりやりたくない......
アプリケーション起動時に待ってあげるとうまくいかないか?
→ getApplicationDefaultAsync() 空打ちしても安定しない
コードリーディング
google-auth-library-nodejs/googleauth.ts at master · googleapis/google-auth-library-nodejs
getApplicationDefaultAsync
$HOME/.config/gcloud/application_default_credentials.json に置かれているの知らなかった
isGCE = await this._checkIsGCE();
this.checkIsGCE = await gcpMetadata.isAvailable();
この結果はキャッシュされる
code:google-auth-library/src/auth/googleauth.ts
async _checkIsGCE() {
if (this.checkIsGCE === undefined) {
this.checkIsGCE = await gcpMetadata.isAvailable();
}
return this.checkIsGCE;
}
失敗したらそれが使われ続ける
! コールドスタートしてキャッシュなくて取り直す → そこから失敗し続けるパターン
googleapis/gcp-metadata: Get the metadata from a Google Cloud Platform environment
isAvailable()
gcp-metadata/index.ts at ba8d9f50eac6cf8b439c1b66c48ace146c75f6e2 · googleapis/gcp-metadata
code:gcp-metadata/src/index.ts
cachedIsAvailableResponse = metadataAccessor(
'instance',
undefined,
detectGCPAvailableRetries(),
true
);
metadataAccessor()
https://github.com/googleapis/gcp-metadata/blob/25bc11657001cb6b3807543377d74bafe126ea62/src/index.ts#L49
http リクエスト投げている
${BASE_URL}/${type}${property},
BASE_URL: http://169.254.169.254/computeMetadata/v1
type: instance
property: ''
これが timeoutしている
fastFail=true のとき fastFailMetadataRequest()
https://github.com/googleapis/gcp-metadata/blob/9a78142b093bccd92ded17b88da7219bc87dac4d/src/index.ts#L98
BASE_URL と SECONDARY_URL
SECONDARY_URL: http://metadata.google.internal.
http://169.254.169.254/computeMetadata/v1
http://metadata.google.internal./computeMetadata/v1
return Promise.race([r1, r2]);
race で並列に叩いて早い方を使う!! おもしろい
https://github.com/googleapis/google-auth-library-nodejs/blob/master/src/auth/computeclient.ts
compute client、GCP 実行環境上で動く
https://cloud.google.com/compute/docs/storing-retrieving-metadata?hl=ja
GCE metadata サーバー
Cloud Shell 内からだと metadata.google.internal が見える
code:shell
pokutuna@cloudshell:~ (pokutuna-playground)$ curl http://metadata.google.internal/computeMetadata/v1/instance/name
devshell-vm-23a348f3-7923-4f31-8fa0-3b12a333847b
Compute client getApplicationDefaultAsync で呼んだ時 serviceAccountEmail: 'default' 以外あるのか?
ぱっと眺めた感じはなさそう
gcloud deploy functions --service-account=... だと default がそれになるのか? そういう気もあまりしないけど
どうやって token とっているの
https://github.com/googleapis/google-auth-library-nodejs/blob/1f4bf6128a0dcf22cfe1ec492b2192f513836cb2/src/auth/computeclient.ts#L95
fetchIdToken
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
デフォルトサービスアカウントの AccessToken が返ってる?
default を任意のメールアドレスにできる?
接続ユーザなり Cloud Shell 立ち上げたユーザなりで制限されていそう
SSRF脆弱性を利用したGCE/GKEインスタンスへの攻撃例 | "><s>はい</s>
#341876 SSRF in Exchange leads to ROOT access in all instances
https://github.com/pokutuna/cloud-functions-playground/tree/master/metadata-server
$ curl -H "Authorization: Bearer $(gcloud --project=pokutuna-dev auth print-identity-token)" 'https://us-central1-pokutuna-dev.cloudfunctions.net/metadata-server'
ユーザのリクエストそのまま Proxy するようなの
GCEのメタデータサーバーを愛でる ~GCEメタデータのすべて~ - Qiita
インスタンスのサービス アカウントの作成と有効化  |  Compute Engine ドキュメント  |  Google Cloud
インスタンス メタデータの格納と取得  |  Compute Engine ドキュメント  |  Google Cloud
関数 ID  |  Google Cloud Functions に関するドキュメント
GCP の Compute Metadata Credentials について
グローバルスコープで GCP クライアントライブラリを new しない
https://github.com/googleapis/google-auth-library-nodejs/issues/798#issuecomment-591622283
ほんとにこれでいいのか??
#GoogleCloud